type Value enum {
    type Object  core::Map[String,Value];
    type Array   core::List[Value];
    type Bool    core::Bool;
    type Number  core::NormalFloat;
    type String  core::String;
    type Null;
};
export function Object: &(core::Map[String,Value]) => Value
    &(x) => { |Value| { |self::Object| x } };
export function Array: &(core::List[Value]) => Value
    &(x) => { |Value| { |self::Array| x } };
export function Bool: &(core::Bool) => Value
    &(x) => { |Value| { |self::Bool| x } };
export function Number: &(core::NormalFloat) => Value
    &(x) => { |Value| { |self::Number| x } };
export function String: &(core::String) => Value
    &(x) => { |Value| { |self::String| x } };
export const Null: Value
    { |Value| { |Null| () } };

export function stringify:
    &(self::Value) => String
    &(v) =>
        switch v:
        case Object object:
            object
                . { List }
                . { Seq }
                . { map &(key,value) =>
                    { "?:?" ({quote key}, {stringify value}) } }
                . { join ',' }
                . { "{?}" },
        case Array array:
            array
                . { Seq }
                . { map stringify }
                . { join ',' }
                . { "[?]" },
        case Bool bool:
            switch bool:
                case Yes: 'true',
                case No:  'false',
            end,
        case Number number:
            { String number },
        case String string:
            { quote string },
        case Null:
            'null',
        end;

export function parse:
    &(String) => Result[self::Value,Error]
    &(input) =>
        let process := { ValueParser () },
        switch { process input }:
        case Success (value, remaining):
            if (remaining.{length} = 0):
                { Success value },
            else:
                let pos := (input.{length} - remaining.{length}),
                { Failure { Error 'redundant input after parsed content'
                    . { &(msg) => { "? (at position ?)" (msg, pos.{String}) } } } },
        case Failure (err, remaining):
            let all := input.{length},
            let rest := remaining.{length},
            let pos := if (rest > 0): (all -! rest), else: (all -! 1),
            { Failure (err wrap &(msg) => { "? (at position ?)" (msg, pos.{String}) }) },
        end;
